package com.tsd.jxc.fin.service.impl;

import com.tsd.common.vo.BatchDeleteLogicVo;
import com.tsd.core.constants.Constants;
import com.tsd.core.thread.ThreadPoolTaskUtil;
import com.tsd.core.utils.DoubleUtil;
import com.tsd.core.utils.HlpUtils;
import com.tsd.core.utils.ListUtil;
import com.tsd.core.vo.PageBean;
import com.tsd.jxc.fin.FinanceConstants;
import com.tsd.jxc.fin.dao.JxcFinancePaymentRequestDetailMapper;
import com.tsd.jxc.fin.dao.JxcFinancePaymentRequestMapper;
import com.tsd.jxc.fin.entity.JxcFinancePaymentRequestDetail;
import com.tsd.jxc.fin.entity.JxcFinancePaymentRequestDetailExt;
import com.tsd.jxc.fin.entity.JxcFinancePaymentRequestExt;
import com.tsd.jxc.fin.service.JxcFinancePaymentRequestDetailService;
import com.tsd.service.BaseServiceImpl;
import com.tsd.system.entity.SysUser;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * 描述：JxcFinancePaymentRequestDetail 服务实现层
 *
 * @author Hillpool
 * @date 2023/02/09 18:00:21
 */
@Service
public class JxcFinancePaymentRequestDetailServiceImpl extends BaseServiceImpl implements JxcFinancePaymentRequestDetailService {

    @Resource
    private JxcFinancePaymentRequestDetailMapper jxcFinancePaymentRequestDetailMapper;
    @Resource
    private JxcFinancePaymentRequestMapper jxcFinancePaymentRequestMapper;

    @Override
    public JxcFinancePaymentRequestDetail getJxcFinancePaymentRequestDetailById(Long id) throws Exception {
        return jxcFinancePaymentRequestDetailMapper.selectByPrimaryKey(id);
    }

    @Override
    public JxcFinancePaymentRequestDetailExt queryBySid(String sid) throws Exception {
        return jxcFinancePaymentRequestDetailMapper.selectBySid(sid);
    }

    @Override
    public void deleteJxcFinancePaymentRequestDetails(List<String> list, SysUser opUser) throws Exception {
        for (String sid : list) {
            JxcFinancePaymentRequestDetail old = jxcFinancePaymentRequestDetailMapper.selectBySid(sid);
            super.checkEmpty(old, "该记录不存在");
            super.autoInjectBaseData(old, opUser, TYPE_DELETE);
            jxcFinancePaymentRequestDetailMapper.updateByPrimaryKeySelective(old);
        }
    }

    @Override
    public void saveJxcFinancePaymentRequestDetail(JxcFinancePaymentRequestDetailExt record, SysUser opUser) throws Exception {
        if (HlpUtils.isEmpty(record.getId())) {
            super.autoInjectBaseData(record, opUser, this.TYPE_CREATE);
            jxcFinancePaymentRequestDetailMapper.insertSelective(record);
        } else {
            super.autoInjectBaseData(record, opUser, this.TYPE_UPDATE);
            jxcFinancePaymentRequestDetailMapper.updateByPrimaryKeySelective(record);
        }
    }

    @Override
    public void saveJxcFinancePaymentRequestDetail(JxcFinancePaymentRequestExt record, SysUser opUser) throws Exception {
        List<JxcFinancePaymentRequestDetailExt> detailExtList = record.getDetail_list();
        super.checkEmpty(detailExtList, "对账明细不能为空");

        List<Long> existIdList = ListUtil.filterMap(detailExtList, t -> !HlpUtils.isEmpty(t.getId()), JxcFinancePaymentRequestDetailExt::getId);

        JxcFinancePaymentRequestDetailExt params = new JxcFinancePaymentRequestDetailExt();
        params.setDr(0);
        params.setRequest_sid(record.getSid());
        List<JxcFinancePaymentRequestDetailExt> oldList = jxcFinancePaymentRequestDetailMapper.selectByEntity(params);

        //删除不存在单据明细
        List<JxcFinancePaymentRequestDetailExt> delList = ListUtil.filter(oldList, t -> !existIdList.contains(t.getId()));
        if (!HlpUtils.isEmptyList(delList)) {
            List<Long> delIds = ListUtil.map(delList, JxcFinancePaymentRequestDetailExt::getId);
            BatchDeleteLogicVo logicVo = new BatchDeleteLogicVo(opUser);
            logicVo.setIdList(delIds);
            jxcFinancePaymentRequestDetailMapper.deleteLogicByIdList(logicVo);
        }

        List<JxcFinancePaymentRequestDetailExt> insertList = new ArrayList<>();
        List<JxcFinancePaymentRequestDetailExt> updateList = new ArrayList<>();
        double totalAmount = 0D, totalPayment = 0D;
        double endAmount = HlpUtils.isEmpty(record.getPre_end_amount()) ? 0D : record.getPre_end_amount().doubleValue();
        List<String> calcAmountTypeList = Arrays.asList(JxcFinancePaymentRequestDetailExt.SRC_TYPE_ORDER, JxcFinancePaymentRequestDetailExt.SRC_TYPE_SEND,
                JxcFinancePaymentRequestDetailExt.SRC_TYPE_CUT, JxcFinancePaymentRequestDetailExt.SRC_TYPE_IN_BILL, JxcFinancePaymentRequestDetailExt.SRC_TYPE_OUT_BILL);
        for (JxcFinancePaymentRequestDetailExt detailExt : detailExtList) {
            detailExt.setRequest_sid(record.getSid());
            if (calcAmountTypeList.contains(detailExt.getSrc_type())) {
                if (HlpUtils.isEmpty(detailExt.getAmount())) {
                    double amount = DoubleUtil.mul(detailExt.getQty(), detailExt.getPrice());
                    detailExt.setAmount(BigDecimal.valueOf(amount));
                }
                totalAmount = DoubleUtil.add(totalAmount, detailExt.getAmount());
                endAmount = DoubleUtil.add(endAmount, detailExt.getAmount());
                detailExt.setRemain_amount(BigDecimal.valueOf(endAmount));
            }
            if (!HlpUtils.isEmpty(detailExt.getPayment_amount())) {
                totalPayment = DoubleUtil.add(totalPayment, detailExt.getPayment_amount());
                endAmount = DoubleUtil.sub(endAmount, detailExt.getPayment_amount());
                detailExt.setRemain_amount(BigDecimal.valueOf(endAmount));
            }
            if (HlpUtils.isEmpty(detailExt.getId())) {
                super.autoInjectBaseData(detailExt, opUser, this.TYPE_CREATE);
                insertList.add(detailExt);
            } else {
                super.autoInjectBaseData(detailExt, opUser, this.TYPE_UPDATE);
                updateList.add(detailExt);
            }
        }
        if (!HlpUtils.isEmptyList(insertList)) {
            ThreadPoolTaskUtil.executeInList4Split(insertList, false, itemList -> jxcFinancePaymentRequestDetailMapper.insertList(itemList));
        }
        if (!HlpUtils.isEmptyList(updateList)) {
            ThreadPoolTaskUtil.executeInList4Split(updateList, false, itemList -> jxcFinancePaymentRequestDetailMapper.updateList(itemList));
        }

        record.setAmount(BigDecimal.valueOf(totalAmount));
        record.setPayment_amount(BigDecimal.valueOf(totalPayment));
        record.setEnd_amount(BigDecimal.valueOf(endAmount));
        jxcFinancePaymentRequestMapper.updateByPrimaryKeySelective(record);

        // 更新对账状态
        this.updatePayReqState(detailExtList, delList, JxcFinancePaymentRequestDetailExt.SRC_TYPE_ORDER, record.getType());
        this.updatePayReqState(detailExtList, delList, JxcFinancePaymentRequestDetailExt.SRC_TYPE_SEND, record.getType());
        this.updatePayReqState(detailExtList, delList, JxcFinancePaymentRequestDetailExt.SRC_TYPE_IN_BILL, record.getType());
        this.updatePayReqState(detailExtList, delList, JxcFinancePaymentRequestDetailExt.SRC_TYPE_OUT_BILL, record.getType());
        this.updatePayReqState(detailExtList, delList, JxcFinancePaymentRequestDetailExt.SRC_TYPE_CUT, record.getType());
        this.updatePayReqState(detailExtList, delList, JxcFinancePaymentRequestDetailExt.SRC_TYPE_FUND, record.getType());
    }

    private void updatePayReqState(List<JxcFinancePaymentRequestDetailExt> detailExtList, List<JxcFinancePaymentRequestDetailExt> delList, String srcType, String type) {
        List<String> orderDetailList = ListUtil.filterMap(detailExtList, t -> srcType.equals(t.getSrc_type()), JxcFinancePaymentRequestDetailExt::getSrc_sid);
        if (!HlpUtils.isEmptyList(orderDetailList)) {
            ThreadPoolTaskUtil.executeInList4Split(orderDetailList, false, itemList -> {
                List<String> parentList = ListUtil.filterMap(detailExtList, t -> itemList.contains(t.getSrc_sid()), JxcFinancePaymentRequestDetailExt::getSrc_parent_sid);
                if (JxcFinancePaymentRequestDetailExt.SRC_TYPE_ORDER.equals(srcType)) {
                    if (FinanceConstants.TYPE_SALE.equals(type)) {
                        jxcFinancePaymentRequestDetailMapper.updateSalePayReqStateBySaleOrderDetailList(itemList, Constants.VALUE_YES);
                        jxcFinancePaymentRequestDetailMapper.updateSalePayReqStateBySaleOrderList(parentList);
                    } else {
                        jxcFinancePaymentRequestDetailMapper.updateBuyPayReqStateByBuyOrderDetailList(itemList, Constants.VALUE_YES);
                        jxcFinancePaymentRequestDetailMapper.updateBuyPayReqStateByBuyOrderList(parentList);
                    }
                } else if (JxcFinancePaymentRequestDetailExt.SRC_TYPE_SEND.equals(srcType)) {
                    jxcFinancePaymentRequestDetailMapper.updateSendPayReqStateBySendDetailList(itemList, type, Constants.VALUE_YES);
                    jxcFinancePaymentRequestDetailMapper.updateSendPayReqStateBySendList(parentList, type);
                } else if (JxcFinancePaymentRequestDetailExt.SRC_TYPE_IN_BILL.equals(srcType)) {
                    jxcFinancePaymentRequestDetailMapper.updateSendPayReqStateByInBillItemList(itemList, Constants.VALUE_YES);
                    jxcFinancePaymentRequestDetailMapper.updateSendPayReqStateByInBillList(parentList);
                } else if (JxcFinancePaymentRequestDetailExt.SRC_TYPE_OUT_BILL.equals(srcType)) {
                    jxcFinancePaymentRequestDetailMapper.updateSendPayReqStateByOutBillItemList(itemList, Constants.VALUE_YES);
                    jxcFinancePaymentRequestDetailMapper.updateSendPayReqStateByOutBillList(parentList);
                } else if (JxcFinancePaymentRequestDetailExt.SRC_TYPE_CUT.equals(srcType)) {
                    jxcFinancePaymentRequestDetailMapper.updatePayReqState4CutMoney(itemList, Constants.VALUE_YES);
                } else {
                    jxcFinancePaymentRequestDetailMapper.updatePayReqState4FundDetail(itemList, Constants.VALUE_YES);
                }
            });
        }
        List<String> delOrderDetailList = ListUtil.filterMap(delList, t -> srcType.equals(t.getSrc_type()), JxcFinancePaymentRequestDetailExt::getSrc_sid);
        if (!HlpUtils.isEmptyList(delOrderDetailList)) {
            ThreadPoolTaskUtil.executeInList4Split(delOrderDetailList, false, itemList -> {
                List<String> parentList = ListUtil.filterMap(detailExtList, t -> itemList.contains(t.getSrc_sid()), JxcFinancePaymentRequestDetailExt::getSrc_parent_sid);
                if (JxcFinancePaymentRequestDetailExt.SRC_TYPE_ORDER.equals(srcType)) {
                    if (FinanceConstants.TYPE_SALE.equals(type)) {
                        jxcFinancePaymentRequestDetailMapper.updateSalePayReqStateBySaleOrderDetailList(itemList, Constants.VALUE_NO);
                        jxcFinancePaymentRequestDetailMapper.updateSalePayReqStateBySaleOrderList(parentList);
                    } else {
                        jxcFinancePaymentRequestDetailMapper.updateBuyPayReqStateByBuyOrderDetailList(itemList, Constants.VALUE_NO);
                        jxcFinancePaymentRequestDetailMapper.updateBuyPayReqStateByBuyOrderList(parentList);
                    }
                } else if (JxcFinancePaymentRequestDetailExt.SRC_TYPE_SEND.equals(srcType)) {
                    jxcFinancePaymentRequestDetailMapper.updateSendPayReqStateBySendDetailList(itemList, type, Constants.VALUE_NO);
                    jxcFinancePaymentRequestDetailMapper.updateSendPayReqStateBySendList(parentList, type);
                } else if (JxcFinancePaymentRequestDetailExt.SRC_TYPE_IN_BILL.equals(srcType)) {
                    jxcFinancePaymentRequestDetailMapper.updateSendPayReqStateByInBillItemList(itemList, Constants.VALUE_NO);
                    jxcFinancePaymentRequestDetailMapper.updateSendPayReqStateByInBillList(parentList);
                } else if (JxcFinancePaymentRequestDetailExt.SRC_TYPE_OUT_BILL.equals(srcType)) {
                    jxcFinancePaymentRequestDetailMapper.updateSendPayReqStateByOutBillItemList(itemList, Constants.VALUE_NO);
                    jxcFinancePaymentRequestDetailMapper.updateSendPayReqStateByOutBillList(parentList);
                } else if (JxcFinancePaymentRequestDetailExt.SRC_TYPE_CUT.equals(srcType)) {
                    jxcFinancePaymentRequestDetailMapper.updatePayReqState4CutMoney(itemList, Constants.VALUE_NO);
                } else {
                    jxcFinancePaymentRequestDetailMapper.updatePayReqState4FundDetail(itemList, Constants.VALUE_NO);
                }
            });
        }
    }

    @Override
    public List<JxcFinancePaymentRequestDetailExt> findJxcFinancePaymentRequestDetails(Map<String, Object> params, PageBean page) throws Exception {
        return jxcFinancePaymentRequestDetailMapper.selectByPage(params, page);
    }

    @Override
    public List<JxcFinancePaymentRequestDetailExt> findJxcFinancePaymentRequestDetails(Map<String, Object> params) throws Exception {
        return jxcFinancePaymentRequestDetailMapper.selectByParams(params);
    }

    @Override
    public List<JxcFinancePaymentRequestDetailExt> queryValidByRequestList(List<String> requestList) {
        return ThreadPoolTaskUtil.queryInList4Split(requestList, list -> jxcFinancePaymentRequestDetailMapper.selectByRequestList(list));
    }
}